package com.shanshan.wheel.rpc.common.remoting.transport.server;

import com.shanshan.wheel.rpc.common.provider.RpcServiceProperties;
import com.shanshan.wheel.rpc.common.provider.ServiceProvider;
import com.shanshan.wheel.rpc.common.remoting.transport.codec.RpcMessageDecoder;
import com.shanshan.wheel.rpc.common.remoting.transport.codec.RpcMessageEncoder;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.logging.LogLevel;
import io.netty.handler.logging.LoggingHandler;
import io.netty.handler.timeout.IdleStateHandler;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.concurrent.TimeUnit;

/**
 * @Description
 * @ClassName NettyServer
 * @Author 山山大魔王
 * @Date 2022/9/4 15:27
 * @Version 1.0
 */
@Component
@Slf4j
public class NettyServer {
    private static Integer PORT;

    @Autowired
    ServiceProvider serviceProvider;

    @Value("${server.port}")
    private int rpc_port;

    @PostConstruct
    public void getEnvironment(){
        PORT = rpc_port;
    }

    /**
     * 服务注册方法
     * @param service 服务的实现
     * @param rpcServiceProperties 服务的属性（版本号+实现类标识group）
     */
    public void registerService(Object service, RpcServiceProperties rpcServiceProperties){
        serviceProvider.publishService(service, rpcServiceProperties);
    }

    public void registerService(Object service){
        serviceProvider.publishService(service);
    }


    public void start() throws UnknownHostException {
        String host = InetAddress.getLocalHost().getHostAddress();
        log.info(host);
        NioEventLoopGroup bossGroup = new NioEventLoopGroup(1);
        NioEventLoopGroup workerGroup = new NioEventLoopGroup();

        try {
            ServerBootstrap serverBootstrap = new ServerBootstrap();

            serverBootstrap.group(bossGroup, workerGroup)
                    .channel(NioServerSocketChannel.class)
                    // 禁用 TCP 的 nagle算法
                    .childOption(ChannelOption.TCP_NODELAY, true)
                    // 开启TCP底层心跳机制
                    .childOption(ChannelOption.SO_KEEPALIVE,true)
                    // 表示系统用于临时存放已完成三次握手的请求的队列的最大长度,如果连接建立频繁，服务器处理创建新连接较慢，可以适当调大这个参数
                    .option(ChannelOption.SO_BACKLOG, 128)
                    .handler(new LoggingHandler(LogLevel.INFO))
                    .childHandler(new ChannelInitializer<SocketChannel>() {
                        @Override
                        protected void initChannel(SocketChannel ch) throws Exception {
                            ChannelPipeline pipeline = ch.pipeline();
                            // 给管道添加IdleStateHandler ，设置为30秒内未执行读取触发
                            pipeline.addLast(new IdleStateHandler(30,0,0, TimeUnit.SECONDS));
                            // 给管道添加编码器
                            pipeline.addLast(new RpcMessageEncoder());
                            // 给管道添加解码器
                            pipeline.addLast(new RpcMessageDecoder());
                            // 给管道添加自定义处理程序
                            pipeline.addLast(new NettyRpcServerHandler());
                        }
                    });

            ChannelFuture cf = serverBootstrap.bind(host, PORT).sync();
            cf.channel().closeFuture().sync();
        } catch (InterruptedException e) {
            log.error("启动服务出现异常",e);
        } finally {
            log.error("关闭 bossGroup 和 workerGroup");
            bossGroup.shutdownGracefully();
            workerGroup.shutdownGracefully();
        }

    }





}
